package org.dromara.exam.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaMode;
import cn.hutool.core.util.IdUtil;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.redis.utils.QueueUtils;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.web.core.BaseController;
import org.dromara.exam.domain.bo.ExamAnswerBo;
import org.dromara.exam.domain.dto.ScoreCalculatorTask;
import org.dromara.exam.domain.vo.ExamAnswerVo;
import org.dromara.exam.domain.vo.ExamProjectVo;
import org.dromara.exam.service.IExamAnswerService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.time.Duration;
import java.util.List;

/**
 * 答题
 *
 * @author xiyin321
 * @date 2024-05-24
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/exam/answer/")
public class ExamAnswerController extends BaseController {
    private final IExamAnswerService examAnswerService;

    /**
     * 分页查询答卷
     */
    @SaCheckPermission(value = {"exam:answer:list","exam:answer:query"}, mode = SaMode.OR)
    @GetMapping("page")
    public TableDataInfo<ExamAnswerVo> page(ExamAnswerBo bo, PageQuery pageQuery) {
        return examAnswerService.queryPage(bo, pageQuery);
    }
    /**
     * 查询答卷列表
     */
    @SaCheckPermission(value = {"exam:answer:list","exam:answer:query"}, mode = SaMode.OR)
    @GetMapping("list")
    public R<List<ExamAnswerVo>> list(ExamAnswerBo bo) {
        return R.ok(examAnswerService.queryList(bo));
    }
    /**
     * 查询排名列表
     */
    @SaCheckPermission("exam:answer:rank")
    @GetMapping("rank")
    public TableDataInfo<ExamAnswerVo> rank(ExamAnswerBo bo, PageQuery pageQuery) {
        return examAnswerService.queryRankPageList(bo, pageQuery);
    }

    /**
     * 查询当前用户的答卷列表
     */
    @SaCheckPermission("exam:answer:query")
    @GetMapping("answerList")
    public R<List<ExamAnswerVo>> queryAnswerListByUserId(ExamAnswerBo bo) {
        return R.ok(examAnswerService.queryProjectListByUserId(bo));
    }


    /**
     * 导出答题列表
     */
    @SaCheckPermission("exam:answer:export")
    @Log(title = "答题", businessType = BusinessType.EXPORT)
    @PostMapping("export")
    public void export(ExamAnswerBo bo, HttpServletResponse response) {
        List<ExamAnswerVo> list = examAnswerService.queryList(bo);
        ExcelUtil.exportExcel(list, "答题", ExamAnswerVo.class, response);
    }

    /**
     * 获取答题详细信息
     *
     * @param id 主键
     */
    @SaCheckPermission("exam:answer:query")
    @GetMapping("{id}")
    public R<ExamAnswerVo> getInfo(@NotNull(message = "主键不能为空")
                                   @PathVariable Long id) {
        return R.ok(examAnswerService.queryById(id));
    }

    /**
     * 新增答卷
     */
    @SaCheckPermission("exam:answer:add")
    @Log(title = "答题", businessType = BusinessType.INSERT)
    @PostMapping()
    public R<ExamAnswerVo> add(@Validated(AddGroup.class) @RequestBody ExamProjectVo bo) {
        return R.ok(examAnswerService.insertByBo(bo));
    }


    /**
     * 暂存答卷
     */
    @SaCheckPermission("exam:answer:edit")
    @Log(title = "答题", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping("tempSave")
    public R<Void> tempSave(@Validated(EditGroup.class) @RequestBody ExamAnswerBo bo) {
        return toAjax(examAnswerService.tempSaveByBo(bo));
    }

    /**
     * 保存答卷
     */
    @SaCheckPermission("exam:answer:edit")
    @Log(title = "答题", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody ExamAnswerBo bo) {
        String taskId = "SCORE_TASK_" + IdUtil.getSnowflakeNextIdStr();
        QueueUtils.addQueueObject("exam:score:queue", new ScoreCalculatorTask(taskId, LoginHelper.getUserId(), bo));
        RedisUtils.setCacheObject("exam:score:status:" + taskId, "processing", Duration.ofMinutes(300));
        return R.ok(taskId);
    }

    /**
     * 修改答卷分数
     * @param bo
     * @return
     */
    @SaCheckPermission("exam:answer:examScore")
    @Log(title = "答题", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping("editScore")
    public R<ExamAnswerVo> editAnswerScore(@Validated(EditGroup.class) @RequestBody ExamAnswerBo bo) {
        return R.ok(examAnswerService.updateScoreById(bo));
    }

    /**
     * 删除答卷
     *
     * @param ids 主键串
     */
    @SaCheckPermission("exam:answer:remove")
    @Log(title = "答题", businessType = BusinessType.DELETE)
    @DeleteMapping("{ids}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] ids) {
        return toAjax(examAnswerService.deleteWithValidByIds(List.of(ids), true));
    }
}
